home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
101-125
/
118
/
empire
/
src
/
source.zoo
/
scan.d
< prev
next >
Wrap
Text File
|
1987-12-02
|
15KB
|
669 lines
#empire.g
#empfunc.g
uint
MAX_CONDITIONS = 8, /* max # '?' conditions */
MAX_SHIPS = 32; /* max # specific ships */
/* negative codes for a unit to be compared: */
int
U_EFFICIENCY = -1,
U_MOBILITY = -2,
U_DEFENDED = -3,
U_MILITARY = -4,
U_PLANES = -5,
U_MINERALS = -6,
U_PRODUCTION = -7,
U_CONTRACTED = -8,
U_SHELLS = -9,
U_ORE = -10,
U_GOLD = -11,
U_CHECKPOINT = -12,
U_CIVILIANS = -13,
U_GUNS = -14,
U_BARS = -15,
U_DESIGNATION = -16,
U_OWNER = -17;
*char UNITS =
"efficiency\e"
"mobility\e"
"defended\e"
"military\e"
"planes\e"
"minerals\e"
"production\e"
"contracted\e"
"shells\e"
"ore\e"
"gold\e"
"checkpoint\e"
"civilians\e"
"guns\e"
"bars\e"
"designation\e"
"owner\e";
type
Condition_t = struct {
int c_left;
char c_operator;
int c_right;
},
ShipPattern_t = enum {
shp_none, /* no conditions */
shp_list, /* list of ship numbers */
shp_box, /* sectors they are in */
shp_fleet /* a fleet they are in */
};
uint ConditionCount;
[MAX_CONDITIONS] Condition_t Condition;
int BoxTop, BoxBottom, BoxLeft, BoxRight;
Sector_t CurrentSector;
bool MapHook;
ShipPattern_t ShipPatternType;
uint ShipCount;
[MAX_SHIPS] uint ShipList;
char ShipFleet;
Ship_t CurrentShip;
/*
* member -
* return true if character is in string
*/
proc member(*char set; char element)bool:
while set* ~= '\e' and set* ~= element do
set := set + sizeof(char);
od;
set* = element
corp;
/*
* getValue -
* get a value for a condition.
*/
proc getValue(bool isRight, isShip)bool:
*char p;
uint res;
int valu;
char ch;
bool ok;
ok := true;
if InputPtr* >= '0' and InputPtr* <= '9' then
/* a simple numeric value */
valu := 0;
while InputPtr* >= '0' and InputPtr* <= '9' do
valu := valu * 10 + (InputPtr* - '0');
InputPtr := InputPtr + 1;
od;
elif (InputPtr + 1)* < 'a' or (InputPtr + 1)* > 'z' then
/* assume its a one-character designation character */
ch := InputPtr*;
InputPtr := InputPtr + 1;
if isShip then
if not member(&ShipChar[0], ch) then
err("invalid ship designation in condition");
ok := false;
else
valu := getIndex(&ShipChar[0], ch);
fi;
else
if not member(&SectorChar[0], ch) then
err("invalid sector designation in condition");
ok := false;
else
valu := getIndex(&SectorChar[0], ch);
fi;
fi;
else
p := InputPtr;
while InputPtr* >= 'a' and InputPtr* <= 'z' do
InputPtr := InputPtr + sizeof(char);
od;
ch := InputPtr*;
InputPtr* := '\e';
res := lookupCommand(UNITS, p);
if res = 0 then
err("invalid unit in condition");
ok := false;
elif res = 1 then
err("ambiguous unit in condition");
ok := false;
else
InputPtr* := ch;
valu := 1 - make(res, int);
fi;
fi;
if ok then
if isRight then
Condition[ConditionCount].c_right := valu;
else
Condition[ConditionCount].c_left := valu;
fi;
fi;
ok
corp;
/*
* getOperator -
* get a valid condition operator.
*/
proc getOperator()bool:
if InputPtr* = '<' or InputPtr* = '>' or InputPtr* = '=' or
InputPtr* = '\#' then
Condition[ConditionCount].c_operator := InputPtr*;
InputPtr := InputPtr + 1;
true
else
err("invalid operator in condition");
false
fi
corp;
/*
* parseConditions -
* parse a set of conditions from the command line, and store them into
* the condition array. 'isShip' is true if we want conditions that will
* apply to ship (some limitations). We return 'true' if all went well.
*/
proc parseConditions(bool isShip)bool:
char operator, desig;
bool done, hadError;
if InputPtr* = '/' then
/* special case, allow '/x' to mean '?des=x' */
InputPtr := InputPtr + 1;
ConditionCount := 0;
Condition[0].c_left := U_DESIGNATION;
Condition[0].c_operator := '=';
if getValue(true, isShip) then
if Condition[0].c_right < 0 then
err("must use designation letter with '/'");
false
else
ConditionCount := 1;
true
fi
else
false
fi
else
ConditionCount := 0;
if InputPtr* = '?' then
InputPtr := InputPtr + 1;
done := false;
hadError := false;
while not done and not hadError do
if InputPtr* = '\e' or InputPtr* = ' ' or InputPtr* = '\t' then
/* no more conditions */
done := true;
elif ConditionCount = MAX_CONDITIONS then
err("too many conditions");
hadError := true;
elif getValue(false, isShip) and
getOperator() and
getValue(true, isShip) then
if Condition[ConditionCount].c_left = U_DESIGNATION and
Condition[ConditionCount].c_right < 0 or
Condition[ConditionCount].c_right = U_DESIGNATION
and Condition[ConditionCount].c_left < 0 then
err("invalid use of designation character");
hadError := true;
elif Condition[ConditionCount].c_left >= 0 and
Condition[ConditionCount].c_right >= 0 then
err("invalid condition - no field");
hadError := true;
else
ConditionCount := ConditionCount + 1;
if InputPtr* = '&' then
InputPtr := InputPtr + sizeof(char);
elif InputPtr* ~= '\e' and InputPtr* ~= ' ' and
InputPtr* ~= '\t' then
err("syntax error in conditions");
hadError := true;
fi;
fi;
else
hadError := true;
fi;
od;
not hadError
else
true
fi
fi
corp;
/*
* getShips -
* get a ships specifier
*/
proc getShips()bool:
*char p;
uint shipNumber;
bool hadError, done;
if InputPtr* = '?' or InputPtr* = '/' then
ShipPatternType := shp_none;
parseConditions(true)
elif InputPtr* = '*' or InputPtr* >= 'a' and InputPtr* <= 'z' or
InputPtr* >= 'A' and InputPtr* <= 'Z' then
ShipPatternType := shp_fleet;
ShipFleet := InputPtr*;
InputPtr := InputPtr + sizeof(char);
parseConditions(true)
elif InputPtr* = '-' or InputPtr* = '\#' then
ShipPatternType := shp_box;
getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
parseConditions(true)
elif InputPtr* < '0' or InputPtr* > '9' then
err("invalid ships specification");
false
else
p := InputPtr;
while p* >= '0' and p* <= '9' do
p := p + 1;
od;
if p* = ',' or p* = ':' then
ShipPatternType := shp_box;
getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
parseConditions(true)
else
/* we have a list of ship numbers separated by '/'s */
ShipPatternType := shp_list;
ShipCount := 0;
hadError := false;
done := false;
while not done and not hadError do
if ShipCount = MAX_SHIPS then
err("too many ships listed");
hadError := true;
elif InputPtr* < '0' or InputPtr* > '9' then
err("invalid ship number");
hadError := true;
else
shipNumber := 0;
while InputPtr* >= '0' and InputPtr* <= '9' do
shipNumber := shipNumber * 10 + (InputPtr* - '0');
InputPtr := InputPtr + sizeof(char);
od;
if shipNumber >= World.w_shipNext then
err("ship number too big");
hadError := true;
fi;
ShipList[ShipCount] := shipNumber;
ShipCount := ShipCount + 1;
if InputPtr* = '/' then
InputPtr := InputPtr + sizeof(char);
elif InputPtr* = '\e' or InputPtr* = '?' or
InputPtr* = ' ' or InputPtr* = '\t' then
done := true;
else
err("invalid character in ship list");
hadError := true;
fi;
fi;
od;
not hadError and parseConditions(true)
fi
fi
corp;
/*
* setAllShips -
* special entry point so cmd_ships can request all ships
*/
proc setAllShips()void:
ShipPatternType := shp_none;
ConditionCount := 0;
corp;
/*
* reqShips - request/get a ships list
*/
proc reqShips(*char prompt)bool:
bool gotOne;
if InputPtr* = '\e' then
gotOne := true;
while
write(PromptOut; prompt);
if not readLine(&InputBuffer[0], INPUT_LENGTH) or
InputBuffer[0] = '\e' then
pretend(ioerror(Chin), void);
gotOne := false;
false
else
InputPtr := &InputBuffer[0];
skipBlanks();
not getShips()
fi
do
od;
gotOne
else
getShips()
fi
corp;
/*
* getConditionValue -
* return the int giving the appropriate value for a condition.
*/
proc getConditionValue(int valu; bool isShip)int:
if valu >= 0 then
valu
else
if isShip then
case valu
incase U_CIVILIANS:
incase U_MILITARY:
make(CurrentShip.sh_crew, int)
incase U_SHELLS:
CurrentShip.sh_shells
incase U_GUNS:
CurrentShip.sh_guns
incase U_PLANES:
CurrentShip.sh_planes
incase U_ORE:
CurrentShip.sh_ore
incase U_BARS:
CurrentShip.sh_bars
incase U_DESIGNATION:
CurrentShip.sh_type - st_first
incase U_EFFICIENCY:
CurrentShip.sh_efficiency
incase U_MOBILITY:
CurrentShip.sh_mobility
incase U_OWNER:
CurrentShip.sh_owner
default:
err("unknown ship unit");
0
esac
else
case valu
incase U_EFFICIENCY:
make(CurrentSector.s_efficiency, int)
incase U_MOBILITY:
CurrentSector.s_mobility
incase U_DEFENDED:
if CurrentSector.s_defender = NO_DEFEND then
0
else
1
fi
incase U_MILITARY:
readQuan(CurrentSector, it_military)
incase U_PLANES:
readQuan(CurrentSector, it_planes)
incase U_MINERALS:
CurrentSector.s_iron
incase U_PRODUCTION:
CurrentSector.s_production
incase U_CONTRACTED:
if CurrentSector.s_price ~= 0 then
1
else
0
fi
incase U_SHELLS:
readQuan(CurrentSector, it_shells)
incase U_ORE:
readQuan(CurrentSector, it_ore)
incase U_GOLD:
CurrentSector.s_gold
incase U_CHECKPOINT:
CurrentSector.s_checkPoint
incase U_CIVILIANS:
readQuan(CurrentSector, it_civilians)
incase U_GUNS:
readQuan(CurrentSector, it_guns)
incase U_BARS:
readQuan(CurrentSector, it_bars)
incase U_DESIGNATION:
CurrentSector.s_type - s_first
incase U_OWNER:
CurrentSector.s_owner
default:
err("unknown sector unit");
0
esac
fi
fi
corp;
/*
* checkConditions -
* see if the setup conditions match the current ship/sector
*/
proc checkConditions(bool isShip)bool:
uint condition;
int left, right;
bool matching;
matching := true;
condition := 0;
while condition ~= ConditionCount and matching do
left := getConditionValue(Condition[condition].c_left , isShip);
right := getConditionValue(Condition[condition].c_right, isShip);
matching :=
case Condition[condition].c_operator
incase '<':
left < right
incase '>':
left > right
incase '=':
left = right
incase '\#':
left ~= right
esac;
condition := condition + 1;
od;
matching
corp;
/*
* scanShips -
* The actual ship scanning routine. It calls its argument proc
* for each ship that meets the set up specs and conditions.
*/
proc scanShips(proc(uint shipNumber; Ship_t sh)void scanner)uint:
Fleet_t fleet;
uint shipNumber, i, count;
int r, c;
count := 0;
if World.w_shipNext ~= 0 then
if ShipPatternType = shp_list then
i := 0;
while i ~= ShipCount and not gotControlC() do
shipNumber := ShipList[i];
readShip(shipNumber, CurrentShip);
if CurrentShip.sh_owner = ThisCountryNumber or
ThisCountryNumber = DEITY then
if checkConditions(true) then
count := count + 1;
scanner(shipNumber, CurrentShip);
fi;
fi;
i := i + 1;
od;
elif ShipPatternType = shp_fleet and ShipFleet ~= '*' then
if ThisCountry*.c_fleets[fleetPos(ShipFleet)] = NO_FLEET then
err("you have no such fleet");
else
readFleet(ThisCountry*.c_fleets[fleetPos(ShipFleet)], fleet);
if fleet.f_count = 0 then
err("fleet has no ships");
else
i := 0;
while i ~= fleet.f_count and not gotControlC() do
readShip(fleet.f_ship[i], CurrentShip);
if checkConditions(true) then
count := count + 1;
scanner(fleet.f_ship[i], CurrentShip);
fi;
i := i + 1;
od;
fi;
fi;
else
shipNumber := 0;
while shipNumber ~= World.w_shipNext and not gotControlC() do
readShip(shipNumber, CurrentShip);
if CurrentShip.sh_owner = ThisCountryNumber or
ThisCountryNumber = DEITY then
if
case ShipPatternType
incase shp_none:
true
incase shp_box:
r := unTransRow(ThisCountryNumber,
CurrentShip.sh_row);
c := unTransCol(ThisCountryNumber,
CurrentShip.sh_col);
r >= BoxTop and r <= BoxBottom and
c >= BoxLeft and c <= BoxRight
incase shp_fleet: /* '*' fleet */
CurrentShip.sh_fleet = ShipFleet
esac
then
if checkConditions(true) then
count := count + 1;
scanner(shipNumber, CurrentShip);
fi;
fi;
fi;
shipNumber := shipNumber + 1;
od;
fi;
fi;
count
corp;
/*
* getSectors -
* get a sectors specifier
*/
proc getSectors()bool:
getBox(&BoxTop, &BoxBottom, &BoxLeft, &BoxRight) and
parseConditions(false)
corp;
/*
* reqSectors - request/get a sectors specification
*/
proc reqSectors(*char prompt)bool:
bool gotOne;
MapHook := false;
if InputPtr* = '\e' then
gotOne := true;
while
write(PromptOut; prompt);
if not readLine(&InputBuffer[0], INPUT_LENGTH) or
InputBuffer[0] = '\e' then
pretend(ioerror(Chin), void);
gotOne := false;
false
else
InputPtr := &InputBuffer[0];
skipBlanks();
not getSectors()
fi
do
od;
gotOne
else
getSectors()
fi
corp;
/*
* setMapHook - set the special flag for map generation.
*/
proc setMapHook()void:
MapHook := true;
corp;
/*
* scanSectors -
* The actual sector scanning routine. It calls its argument proc
* for each sector that meets the set up specs and conditions.
*/
proc scanSectors(proc(int row, col; Sector_t s)void scanner)uint:
uint count;
int r, c;
bool aborted;
count := 0;
if MapHook then
mapCoords(BoxLeft, BoxRight);
writeln(Chout;);
fi;
aborted := false;
r := BoxTop;
while r <= BoxBottom and not aborted do
if MapHook then
mapRowStart(r);
fi;
c := BoxLeft;
while c <= BoxRight and not aborted do
accessSector(r, c, CurrentSector);
if ThisCountryNumber = DEITY or
CurrentSector.s_owner = ThisCountryNumber or
MapHook and ConditionCount = 0 then
if checkConditions(false) then
count := count + 1;
scanner(r, c, CurrentSector);
elif MapHook then
mapEmpty();
fi;
elif MapHook then
mapEmpty();
fi;
c := c + 1;
aborted := gotControlC();
od;
if MapHook and not aborted then
mapRowEnd(r);
fi;
r := r + 1;
if gotControlC() then
aborted := true;
fi;
od;
if MapHook and not aborted then
writeln(Chout;);
mapCoords(BoxLeft, BoxRight);
fi;
count
corp;